'''
这是一个数域的元类，并提供常见的数域
'''
import sympy
from fractions import Fraction
from decimal import Decimal
import numbers
class Field(type):
    pool={}
    def __new__(cls,name,base=None):
        if name in Field.pool:
            return Field.pool[name]
        if base:
            def init(self,value):
                if isinstance(value,(base,sympy.core.expr.Expr)):
                    self.value=value
                else:
                    try:
                        self.value=base(str(value))
                    except ValueError:
                        self.value=sympy.Symbol(value)
        else:
            def init(self,value):
                if isinstance(value,(sympy.core.expr.Expr,numbers.Number)):
                    self.value=value
                else:
                    self.value=sympy.Symbol(value)
        def has(self):
            return hash(self.value)
        # 这个数域支持未知数
        def add(self,other):
            if type(self)==type(other):
                return type(self)(self.value+other.value)
            return NotImplemented
        def sub(self,other):
            if type(self)==type(other):
                return type(self)(self.value-other.value)
            return NotImplemented
        def mul(self,other):
            if type(self)==type(other):
                return type(self)(self.value*other.value)
            return NotImplemented
        def div(self,other):
            if type(self)==type(other):
                return type(self)(self.value/other.value)
            return NotImplemented
        def eq(self,other):
            '''
            由于未知数的影响，不能简单判断
            '''
            if type(self)==type(other):
                if self.value==other.value:
                    return 1
                elif isinstance(self.value,sympy.core.expr.Expr) or isinstance(other.value,sympy.core.expr.Expr):
                    return -1
                else:
                    return 0
            return NotImplemented
        def eeq(self,other):
            if type(self)==type(other):
                return self.value==other.value
            return NotImplemented
        def rep(self):
            return str(self.value)
        st=rep
        def ass(self,dic):
            new={}
            for i in dic.items():
                new[i[0].value]=i[1].value
            if  all(isinstance(i,type(self)) for i in dic.values()) and isinstance(self.value,sympy.core.expr.Expr):
                return type(self)(self.value.subs(new))
            return NotImplemented
        attrs={
            'name':name,
            '__init__': init,
            '__hash__':has,
            '__add__': add,
            '__sub__': sub,
            '__mul__': mul,
            '__truediv__': div,
            'eq': eq,
            '__eq__':eeq,
            '__repr__':rep,
            '__str__':st,
            'ass':ass
        }
        new=super().__new__(cls,name,(),attrs)
        Field.pool[name]=new
        return new
    def __init__(cls,name,base=None):
        pass
Q=Field('Q',Fraction)
R=Field('R',Decimal)
C=Field('C',complex)
F=Field('F')
